/**
 * File  : SocketAddr.cc
 * Time  : 2015-01-04 16:35
 * Author: KashingLee
 * Ref   : Null
 */
#include "SocketAddr.h"

SocketAddr::SocketAddr() :is_v6(false) {
  addr_v4_ = new struct sockaddr_in;
  bzero(addr_v4_, sizeof(struct sockaddr_in));
}

SocketAddr::SocketAddr(sa_family_t family, in_port_t port, in_addr_t addr)\
    : is_v6(false) {
  addr_v4_ = new struct sockaddr_in;
  bzero(addr_v4_, sizeof(struct sockaddr_in));
  addr_v4_->sin_family = family;
  addr_v4_->sin_addr.s_addr = htonl(addr);
  addr_v4_->sin_port = htons(port);
}

SocketAddr::SocketAddr(sa_family_t family, in_port_t port, const char *addr)\
    : is_v6(false) {
  addr_v4_ = new struct sockaddr_in;
  bzero(addr_v4_, sizeof(struct sockaddr_in));
  addr_v4_->sin_family = family;
  addr_v4_->sin_port = htons(port);
  //TODO
  if (1 != inet_pton(family, addr, &addr_v4_->sin_addr.s_addr)) {
    throw 1;
  }
}

SocketAddr::~SocketAddr() {
  bzero(addr_v4_, sizeof(struct sockaddr_in));
  delete addr_v4_; 
}

void SocketAddr::SetFamily(sa_family_t family) {
  addr_v4_->sin_family = family; 
}

void SocketAddr::SetPort  (in_port_t port){
  addr_v4_->sin_port = htons(port);
}

void SocketAddr::SetAddr  (in_addr_t addr) {
  addr_v4_->sin_addr.s_addr = htonl(addr);
}

void SocketAddr::SetAddr  (const char *addr) {
  //TODO exceptions
  if (addr_v4_->sin_family) {
    int tmp = inet_pton(addr_v4_->sin_family, addr, &addr_v4_->sin_addr);
    if (1!=tmp) {
      throw tmp;
    }
  } else {
    throw 2;
  }
}

uint16_t SocketAddr::Port() {
  return ntohs(addr_v4_->sin_port);
}

string SocketAddr::AddrToString() {
  char *str = new char[INET_ADDRSTRLEN]; 
  inet_ntop(addr_v4_->sin_family, &addr_v4_->sin_addr, str, INET_ADDRSTRLEN);
  string tmp(str);
  delete str;
  return tmp;
}

uint32_t SocketAddr::Addr() {
  return ntohl(addr_v4_->sin_addr.s_addr);
}

uint8_t  SocketAddr::Family() {
  return addr_v4_->sin_family;
}
